package corretor;

import dados.Questao;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import versao.Metodos;
import logica.Arquivos;
import logica.Constantes;
import dados.Aluno;
import dados.ArquivoFonte;
import dados.BancoQuestoes;
import dados.LinhaGabarito;
import dados.PastaCorrecao;
import dados.QuestaoProva;
import dados.Teste;
import dados.Saidas;

public class Correcao {  
    Aluno aluno = null;
    
    private static Correcao instancia = null;
    
    /** Cria uma nova inst�ncia da classe Correcao. */
    public Correcao(Aluno aluno) {
        this.aluno = aluno;
        instancia = this;
    }
    
    /**
     * Cria um diret�rio para cada quest�o do aluno passado no construtor.
     */
    public void criarDiretorios() throws IOException {
        ArquivoFonte[] arquivosFontes = aluno.getFontes();
        ArrayList<ArquivoFonte> novosArquivosFontes = new ArrayList<ArquivoFonte>();
        
        for (int i = 0; i <= arquivosFontes.length - 1; i++) {
            ArquivoFonte arquivoFonte = arquivosFontes[i];
            File arqFonte = arquivoFonte.getArquivo();
            
            File diretorio = aluno.getDiretorioAluno();
            File pastaFonte = new File(diretorio.getAbsolutePath() + "/" + 
                    arqFonte.getName().substring(0, 
                    arqFonte.getName().length()- 2));
            
            String q = arqFonte.getName().substring(0,Constantes.NARQ_QUE.length());
            if (q.equalsIgnoreCase(Constantes.NARQ_QUE)) {
                try {
                    String temp1 = arqFonte.getName().substring(Constantes.NARQ_QUE.length(), arqFonte.getName().length());
                    String[] temp2 = temp1.split(".c");
                    int nro = Integer.parseInt(temp2[0]);
                    if (pastaFonte.mkdir()) {
                        File arquivoAntigo = new File(diretorio.getAbsolutePath() +
                                "/" + arqFonte.getName());
                        String texto = Arquivos.getTextoArquivo(arquivoAntigo);
                        arquivoAntigo.delete();
                        File novoArquivo = new File(pastaFonte.getAbsolutePath() +
                               "/" + arqFonte.getName());
                        Arquivos.salvarArquivo(novoArquivo, texto);
                        ArquivoFonte novoArquivoFonte = new ArquivoFonte(novoArquivo);
                        while (novosArquivosFontes.size() < (nro - 1)) {
                            novosArquivosFontes.add(null);
                        }
                        novosArquivosFontes.add(nro - 1, novoArquivoFonte);
                    }
                } catch (NumberFormatException ex) {
                    //ignorando
                }
            }
        }
        aluno.setFontes((ArquivoFonte[])novosArquivosFontes.toArray(new ArquivoFonte[] {}));
    }
    
    public void criarArquivoQuestoesAluno() throws IOException {
        ArquivoFonte[] fontes = aluno.getFontes();
        String nomeAluno = aluno.getDiretorioAluno().getName();
        String texto = nomeAluno + "\n\n";
        int cont = 1;
        for (ArquivoFonte fonte : fontes) {
            if (fonte != null) {
                File arquivo = fonte.getArquivo();
                texto += "-----------------------" + "Questao " + cont + 
                        "-----------------------\n";
                texto += Arquivos.getTextoArquivo(arquivo) + "\n\n";
            }
            cont++;
        }
        File dirRelatorios = new File(PastaCorrecao.getInstancia().getDiretorio() +
                "/relatorios/");
        if (!dirRelatorios.exists()) dirRelatorios.mkdir();
        File arqAluno = new File(dirRelatorios + "/" + nomeAluno + ".txt");
        Arquivos.salvarArquivo(arqAluno, texto);
    }
    
    public void adicionaRelatorioArquivoAluno(int nroQuestao, ArrayList<Saidas> saidas) throws IOException {
        String nomeAluno = aluno.getDiretorioAluno().getName();
        File dirRelatorios = new File(PastaCorrecao.getInstancia().getDiretorio() +
                "/relatorios/");
        File arqAluno = new File(dirRelatorios.getAbsolutePath() +
                "/" + nomeAluno + ".txt");
        String texto = Arquivos.getTextoArquivo(arqAluno) + "\n\n";
        String abertura = "----------> RELATORIO DA QUESTAO " + (nroQuestao + 1) + " <----------";
        if (texto.contains(abertura)) {
            int indice = texto.indexOf(abertura);
            texto = texto.substring(0, indice);
        }
        texto += abertura + "\n\n";
        texto += "ENUNCIADO\n\n";
        
        int alg = BancoQuestoes.getEscolha();
        int versao = algoritmo(nomeAluno,alg);
        
        ArrayList<Teste> testes = BancoQuestoes.getInstancia().getQuestaoProva(nroQuestao)
                .getQuestao(versao).getTestes();
        texto += BancoQuestoes.getInstancia().getQuestaoProva(nroQuestao)
                .getQuestao(versao).getEnunciado() + "\n\n";
        texto += "PROGRAMA GABARITO\n\n";
        texto += BancoQuestoes.getInstancia().getQuestaoProva(nroQuestao)
                .getQuestao(versao).getGabarito() + "\n\n";
  
        
        for(int i = 0; i < saidas.size(); i++){
            Saidas saida = saidas.get(i);
            String linhasEntrada = testes.get(i).getEntradaConcatenada();
            String linhasGabarito = new String();
            for(LinhaGabarito linha : testes.get(i).getLinhasGabarito()){
                linhasGabarito += linha.getLinhaString() + "\n";
            }
            String linhaSaida = saida.getSaida();
            double notaQuestao = aluno.getFontes()[nroQuestao].getPorcentagem(i);
            texto += "### TESTE " + (i + 1) + " ###\n";
            texto += "### ENTRADA DO PROGRAMA ###\n" + (linhasEntrada != null ? linhasEntrada : "") + "\n\n";
            texto += "### SAIDA DO PROGRAMA ###\n" + linhaSaida + "\n\n";
            texto += "### GABARITO ###\n" + linhasGabarito + "\n\n";
            texto += "NOTA: " + notaQuestao + "\n\n";
                    
                    
        }
        Arquivos.salvarArquivo(arqAluno, texto);
/*
        for(int i = 0; i < saidas.size(); i++){
            Saidas saida = saidas.get(i);
            String linhasEntrada = testes.get(i).getEntradaConcatenada();
            
            ArrayList<QuestaoProva> questoes = BancoQuestoes.getInstancia().getArrayListQuestaoProva();
            int nroQuestoes = questoes.size();
            int limite = nroQuestoes;
            String[] aux = new String[50];
            for(int z = 0; z < 50; z++)
            	aux[z] = "";
            for (int m = 0; m <= limite - 1; m++) {
            	Questao questao = questoes.get(m).getQuestao(versao);
            	ArrayList<Teste> testes2 = questao.getTestes();
            	for (int k = 0; k <= testes2.size() - 1; k++) {
            		Teste teste = testes2.get(k);

            		ArrayList<LinhaGabarito> linhasGabarito2 = teste.getLinhasGabarito();
            		ModeloLinhaGabarito modeloLinhaGabarito = teste.getModeloLinhaGabarito();
            		int limiteLinhas = linhasGabarito2.size();
            		for (int n = 0; n <= limiteLinhas - 1; n++) {
            			int limiteColunas = modeloLinhaGabarito.getNroColunas();
            			aux[n] = "";
            			for (int j = 0; j <= limiteColunas - 1; j++) {
            				aux[n] += linhasGabarito2.get(n).getColuna(j);
            				aux[n] += " ";
            			}
            			aux[n] += "\n";
            			System.out.println("\n\n--"+aux[n]+"--\n\n");
            		}
            	}
            }
            
            String linhaSaida = saida.getSaida();
            double notaQuestao = aluno.getFontes()[nroQuestao].getPorcentagem(i);
            texto += "### TESTE " + (i + 1) + " ###\n";
            texto += "### ENTRADA DO PROGRAMA ###\n" + (linhasEntrada != null ? linhasEntrada : "") + "\n\n";
            texto += "### SAIDA DO PROGRAMA ###\n" + linhaSaida + "\n\n";
            texto += "### GABARITOS ###\n" + voltaGab(aux) + "\n\n";
            texto += "NOTA: " + notaQuestao + "\n\n";
        }
        Arquivos.salvarArquivo(arqAluno, texto);
*/
    }
    
    public String voltaGab(String[] aux){
    	String resultado = "";
		for(int i = 0; i < 50; i++){
			if(aux[i] != ""){
				aux[i] = aux[i].replace("null", "");
				resultado += aux[i];
			}	
		}
    	return resultado;
    }
    
    public void adicionaRelatorioArquivoAluno(int nroQuestao, String mensagem) throws IOException {
        String nomeAluno = aluno.getDiretorioAluno().getName();
        System.out.println("Entrou");
        File dirRelatorios = new File(PastaCorrecao.getInstancia().getDiretorio() +
                "/relatorios/");
        File arqAluno = new File(dirRelatorios.getAbsolutePath() +
                "/" + nomeAluno + ".txt");
        String texto = Arquivos.getTextoArquivo(arqAluno) + "\n\n";
        texto += "----------> RELATORIO DA QUESTAO " + ++nroQuestao + " <----------";
        texto += "\n\n" + mensagem;
        Arquivos.salvarArquivo(arqAluno, texto);
    }
    
    public void adicionaRelatorioArquivoAluno(String mensagem) throws IOException {
        String nomeAluno = aluno.getDiretorioAluno().getName();
        File dirRelatorios = new File(PastaCorrecao.getInstancia().getDiretorio() +
                "/relatorios/");
        File arqAluno = new File(dirRelatorios.getAbsolutePath() +
                "/" + nomeAluno + ".txt");
        String texto = Arquivos.getTextoArquivo(arqAluno) + "\n\n";
        texto += mensagem;
        Arquivos.salvarArquivo(arqAluno, texto);
    }
    
    /**
     * Compila todos os arquivos de um determinado aluno.
     */
    public void compilarFontes() throws IOException {
        ArquivoFonte[] arquivosFontes = aluno.getFontes();
        
        for (int i = 0; i <= arquivosFontes.length - 1; i++) {
            ArquivoFonte arquivoFonte = arquivosFontes[i];
            if (arquivoFonte != null) {
                File arqFonte = arquivoFonte.getArquivo();

                Executador ex = new Executador(arqFonte.getParentFile(), new String[] {
                	"gcc", arqFonte.getName(), "-o", arqFonte.getName().substring(0, arqFonte.getName().length() - 2), "-lm"}, null);
                ex.executar();
                if (ex.getValorSaida() != 0) {
                    arquivoFonte.setErroCompilacao(true);
                }
            }
        }
    }
    
    /**
     * Corrige todos os arquivos .c de um determinado aluno, tendo em vista que
     * j� foram inseridos as Entradas e Gabaritos para cada quest�o.
     * 
     * Parametros
     * Se igual a 0 a correção é normal
     * Se igual a 1 a correção é com funções
     * Se igual a 2 a correção é com condicionais
     */
    public void corrigir(int parametros) {
    	String sait = Constantes.SEPARADOR_MENSAGEM_ERRO + " O " + "arquivo de saída deste aluno não foi encontrado. " + Constantes.SEPARADOR_MENSAGEM_ERRO;
        String entt = Constantes.SEPARADOR_MENSAGEM_ERRO + " O " + "arquivo de entrada deste aluno não foi encontrado. " + Constantes.SEPARADOR_MENSAGEM_ERRO;
        ArrayList<QuestaoProva> questoes = BancoQuestoes.getInstancia().getArrayListQuestaoProva();
        ArquivoFonte[] arquivosFonte = aluno.getFontes();
        aluno.reiniciarContagem();
        int funcoes = 1;
        String[] textoRelatorio = null;
        int nroQuestoes = questoes.size();
        int limite = 0;
        Boolean condicionais = false;
        Object n_else = null;
        
        if(parametros == 2){
	        JFrame frame = new JFrame();
	        String bigList[] = new String[5];
	
	        for (int i = 0; i < bigList.length; i++) {
	        	bigList[i] = Integer.toString(i);
	        }
	
	        n_else = JOptionPane.showInputDialog(frame, "Insira a quantidade de 'else'", "Quantidade", JOptionPane.QUESTION_MESSAGE,null,bigList, "Titan");
        }
        
        /*recebe o numero de questoes feitas pelo aluno ou o numero de questoes
        totais. (Qual for maior).*/
        if (nroQuestoes > arquivosFonte.length) {
            limite = arquivosFonte.length;
        } else {
            limite = nroQuestoes;
        }
        //System.out.println("No Questoes: "+limite);
        int alg = BancoQuestoes.getEscolha();
        
        //Faz uma itera��o para cada quest�o
        for (int i = 0; i <= limite - 1; i++) {
            ArquivoFonte arqFonte = arquivosFonte[i];
            
            ArrayList<Saidas> saidas = null;
            String mat = aluno.getDiretorioAluno().getName();

            int versao = algoritmo(mat,alg);
            Questao questao = questoes.get(i).getQuestao(versao);
            double notaMax = questao.getNotaMax();
            if (arqFonte != null && !arqFonte.getErroCompilacao()) {
                ArrayList<Double> pesos = arqFonte.getPorcentagens();
                ArrayList<Teste> testes = questao.getTestes();
                saidas = new ArrayList<Saidas>();
                double notaFinal = 0;
                
                for (int j = 0; j <= testes.size() - 1; j++) {
                    Teste teste = testes.get(j);
                    String textoSaida = "";
                    String textoEntrada = "";
                    File arqEntrada = null;
                    
                    if (teste.getNomeArquivoEntrada() != null) {
                        try {
                            String caminhoArq = arqFonte.getArquivo().getParent();
                            arqEntrada = new File(caminhoArq + "/" + teste.getNomeArquivoEntrada());
                            Arquivos.salvarArquivo(arqEntrada, teste.getEntradaConcatenada());
                        } catch (IOException e) {
                        	textoSaida = entt;
                        }
                    } else {
                        textoEntrada = teste.getEntradaConcatenada();
                    }
                    
                    textoSaida = arqFonte.corrigir(textoEntrada);
                    if (arqEntrada != null) {
                        arqEntrada.delete();
                    }
                    
                    if (questao.getNomeArquivoSaida() != null) {
                        File arqSaida = new File(arqFonte.getArquivo().getParent() + 
                                "/" + questao.getNomeArquivoSaida());
                        try {
                            textoSaida = Arquivos.getTextoArquivo(arqSaida);
                        } catch (IOException e) {
                            textoSaida = sait;
                        }
                        arqSaida.delete();
                    }
                    
                    textoRelatorio = null;
                    if(textoSaida != sait && textoEntrada != entt){
	                    if(teste.getTipo() == Constantes.TIPOA){
	                        textoRelatorio = arqFonte.testarGabaritoA(teste, textoSaida);
	                    } else {
	                        textoRelatorio = arqFonte.testarGabaritoB(teste, textoSaida);
	                    }
                    }else{
                    	arqFonte.addPeso();
                    }
                    
                    if(parametros == 1){
                    	funcoes = arqFonte.usouFuncao();
                    }else if(parametros == 2){
                    	condicionais = arqFonte.condicionais(Integer.parseInt((String) n_else)); 
                    }
                    
                    if(parametros == 2 && !condicionais){
                    	String aux = textoRelatorio[1];
                    	textoRelatorio = null;
                    	textoRelatorio = new String[2];
                    	textoRelatorio[0] = "O aluno não utilizou a quantidade correta de condicionais";
                    	textoRelatorio[1] = aux;
                    	textoSaida = "";
                    }
                    
                    if(parametros == 1 && funcoes == 0){
                    	String aux = textoRelatorio[1];
                    	textoRelatorio = null;
                    	textoRelatorio = new String[2];
                    	textoRelatorio[0] = "O aluno não utilizou funções";
                    	textoRelatorio[1] = aux;
                    	textoSaida = "";
                    }
                    
                    Saidas saida = new Saidas(textoSaida, textoRelatorio);
                    saidas.add(saida);
                    notaFinal += (pesos.get(j).intValue() * (notaMax * teste.getPorcentagemNotaMax())) / 10000;
                }
                if((parametros == 1 && funcoes == 0) || (parametros == 2 && !condicionais)){
                	aluno.addNotaQuestao(0);
                }else{
                	aluno.addNotaQuestao((int) notaFinal);
                }
                arqFonte.setSaidas(saidas);
                try {
                	if((parametros == 1 && funcoes == 0) || (parametros == 2 && !condicionais)){
                		adicionaRelatorioArquivoAluno(i, textoRelatorio[0]);
                	}else{
                		adicionaRelatorioArquivoAluno(i, saidas);
                	}
                } catch (IOException e) {
                        e.printStackTrace();
                }
            } else {
                if (arqFonte == null) {
                    try {
                        adicionaRelatorioArquivoAluno(i, "O Aluno não fez esta Questão!");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else if (arqFonte.getErroCompilacao()) {
                	System.out.println("-- 3");
                    try {
                        adicionaRelatorioArquivoAluno(i, "Erro de Compilação nesta Questão!");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                aluno.addNotaQuestao(0);
            }
        }
        
        try{
            adicionaRelatorioArquivoAluno("NOTA TOTAL: " + aluno.getNotaFinal());
        }catch(IOException e){
            e.printStackTrace();
        }   
    }
    
    public String imprime(int i, int limiteColunas, ArrayList<LinhaGabarito> linhasGabarito){
    	String linhax = "";
    	for (int j = 0; j <= limiteColunas - 1; j++) {
    		linhax += linhasGabarito.get(i).getColuna(j);
    		if(j != limiteColunas)
    			linhax += " ";
    	}
    	return linhax;
    }

    private int algoritmo(String mat, int esc){
    	Metodos mv = null;
    	
    	if(BancoQuestoes.getSimulado() == 1){
    		mv = new Metodos(1);
    	}else{
    		mv = new Metodos(4);
    	}
    	int versao = mv.initMetodos(mat, esc);
    	
		return versao;
    }
}